#ifndef KPEXTBASECOMPUTE_H
#define KPEXTBASECOMPUTE_H

#include "kpextVkContext.h"

namespace kpext {

class BaseCompute : public IRecordCommands
{

public:
    explicit BaseCompute(kpextVkContext * vkCtx);
    virtual ~BaseCompute() override;

    /**
     * @brief 重新构建计算管线及相关资源
     * @param spirv 计算管线使用的spirv着色器代码
     * @param bufs  生成描述符集和计算管线布局的储存缓冲(glsl storage buffer)
     * @param specConsts  用于spirv着色器代码的特化常量
     * @param pushConsts  用于spirv着色器代码的推送常量
     * @param workCount  用于计算着色器dispatch的工作组数量
     */
    virtual void rebuild(const std::vector<uint32_t> & spirv,
                         const std::vector<std::shared_ptr<BaseBuffer>> & bufs,
                         const std::vector<uint32_t> & specConsts,
                         const std::vector<uint32_t> & pushConsts,
                         const std::array<uint32_t, 3> & workCount
                         );

    /**
     * @brief 以新的储存缓冲重新构建计算管线及相关资源
     * @param bufs 写入生成描述符集信息的储存缓冲(glsl storage buffer)
     */
    virtual void rebuild(const std::vector<std::shared_ptr<BaseBuffer>> & bufs);

    /**
     * @brief 设置是否使能计算后缓冲区屏障，初始时是使能的
     * @param en  是否使能
     */
    virtual void enablePostBarrier(bool en);

    // IRecordCommands interface
    void record(const vk::CommandBuffer &commandBuffer) override;

protected:

    /**
     * @brief 有这个void参数的构造函数才能匿名子类化
     */
    BaseCompute() :
        m_vkCtx(nullptr),
        m_cols(0),
        m_rows(0),
        m_inBuf(nullptr),
        m_outBuf(nullptr),
        m_postBarrier(true),
        m_cmdBarrier(),
        m_descrPool(nullptr),
        m_descrSetlayout(nullptr),
        m_descrSet(nullptr),
        m_pipeline(nullptr),
        m_workCount({1, 1, 1})
    {}
    /**
     * @brief vulkan 上下文件运行环境
     */
    kpextVkContext * m_vkCtx;

    /**
     * @brief 输入输出尺寸， 给子类用的
     */
    uint32_t m_cols;
    uint32_t m_rows;

    /**
     * @brief 输入输出缓冲， 给子类用的
     */
    BaseBuffer * m_inBuf, * m_outBuf;

    /**
     * @brief 计算完后是否进行屏障
     */
    bool m_postBarrier;

    /**
     * @brief 屏障命令
     */
    kpext::CmdBuffersMemBarrier m_cmdBarrier;

    /**
     * @brief 描述符池
     */
    std::shared_ptr<DescriptorPool> m_descrPool;

    /**
     * @brief vulkan 描述符集布局
     */
    std::shared_ptr<vk::DescriptorSetLayout> m_descrSetlayout;

    /**
     * @brief vulkan 描述符集
     */
    std::shared_ptr<vk::DescriptorSet> m_descrSet;

    /**
     * @brief 计算管线
     */
    std::shared_ptr<kpext::ComputePipeline> m_pipeline;

    /**
     * @brief vulkan dipatch计算着色器的work count
     */
    std::array<uint32_t, 3> m_workCount;


}; //class kpext::BaseCompute


} //namespace kpext

#endif // KPEXTBASECOMPUTE_H
